import {
  Controller,
  UseGuards,
  BadRequestException,
  UploadedFile,
} from '@nestjs/common';
import {
  Crud,
  CrudController,
  Override,
  CrudRequest,
  ParsedRequest,
  ParsedBody,
} from '@nestjsx/crud';
import { ApiTags, ApiBearerAuth, ApiConsumes } from '@nestjs/swagger';
import { FileUtils } from '@/utils';
import { deserialize } from 'class-transformer';
import { RequestDtoRelationTransformer } from '@/interfaces';
import { AuthGuard } from '@/guards';
import { Score, ResourceFile, Song } from '../entities';
import { ScoresService } from '../services';
import { User } from '@/modules/users';

@Crud({
  model: {
    type: Score,
  },
  query: {
    limit: 25,
    maxLimit: 100,
    join: {
      file: {
        allow: ['mimetype', 'size', 'path'],
      },
      uploadedByUser: {},
      relatedSong: {},
    },
  },
  routes: {
    exclude: ['createManyBase'],
    createOneBase: {
      interceptors: [FileUtils.singleFileUploader('file', ['pdf'])],
    },
    updateOneBase: {
      interceptors: [FileUtils.singleFileUploader('file', ['pdf'])],
    },
    replaceOneBase: {
      interceptors: [FileUtils.singleFileUploader('file', ['pdf'])],
    },
    deleteOneBase: {
      decorators: [UseGuards(AuthGuard), ApiBearerAuth()],
    },
  },
})
@ApiTags('scores')
@Controller('resources/scores')
// eslint-disable-next-line prettier/prettier
export class ScoresController implements CrudController<Score>, RequestDtoRelationTransformer<Score> {
  constructor(public service: ScoresService) {}

  get base(): CrudController<Score> {
    return this;
  }

  dtoRelationTransform(dto: Score) {
    try {
      if (typeof dto.file === 'string') {
        dto.file = deserialize(ResourceFile, dto.file);
      }
      if (typeof dto.uploadedByUser === 'string') {
        dto.uploadedByUser = deserialize(User, dto.uploadedByUser);
      }
      if (typeof dto.relatedSong === 'string') {
        dto.relatedSong = deserialize(Song, dto.relatedSong);
      }
    } catch (e) {
      if (e instanceof SyntaxError) {
        throw new BadRequestException(e.message, e.name);
      }
      throw new BadRequestException();
    }
    return dto;
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @Override()
  createOne(
    @ParsedRequest() req: CrudRequest,
    @ParsedBody() dto: Score,
    @UploadedFile() file: Express.Multer.File,
  ) {
    dto = this.dtoRelationTransform(dto);
    if (file) {
      dto.file = new ResourceFile(file);
    }
    return this.base.createOneBase(req, dto);
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @Override()
  updateOne(
    @ParsedRequest() req: CrudRequest,
    @ParsedBody() dto: Score,
    @UploadedFile() file: Express.Multer.File,
  ) {
    dto = this.dtoRelationTransform(dto);
    if (file) {
      dto.file = new ResourceFile(file);
    }
    return this.base.updateOneBase(req, dto);
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @Override()
  replaceOne(
    @ParsedRequest() req: CrudRequest,
    @ParsedBody() dto: Score,
    @UploadedFile() file: Express.Multer.File,
  ) {
    dto = this.dtoRelationTransform(dto);
    if (file) {
      dto.file = new ResourceFile(file);
    }
    return this.base.replaceOneBase(req, dto);
  }
}
